package com.minelx.autocha;

import org.openqa.selenium.chrome.ChromeDriver;

import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Stream.generate;

public class PooledWebBrowserFactory implements IWebBrowserFactory, AutoCloseable {

	private final BlockingQueue<PooledBrowser> idleBrowsers;

	private final List<IWebBrowser> sourceBrowsers;

	public PooledWebBrowserFactory(IWebBrowserFactory delegator, int size) {
		sourceBrowsers = generate(delegator::createBrowser)
				.limit(size)
				.collect(toList());
		idleBrowsers = new ArrayBlockingQueue<>(sourceBrowsers.size(),
				true,
				sourceBrowsers.stream().map(PooledBrowser::new).collect(toList()));
	}

	@Override
	public IWebBrowser createBrowser() {
		try {
			return idleBrowsers.poll(5, TimeUnit.MINUTES);
		} catch (InterruptedException e) {
			throw new IllegalStateException("interrupted while polling.", e);
		}
	}

	public int idleCount() {
		return idleBrowsers.size();
	}

	@Override
	public void close() {
		// close all
		sourceBrowsers.forEach(IWebBrowser::close);
	}

	private class PooledBrowser implements IWebBrowser {
		private final IWebBrowser delegator;

		public PooledBrowser(IWebBrowser delegator) {
			this.delegator = delegator;
		}

		@Override
		public void open(String s) {
			delegator.open(s);
		}

		@Override
		public WebNode id(String s) {
			return delegator.id(s);
		}

		@Override
		public WebNode selector(String s) {
			return delegator.selector(s);
		}

		@Override
		public ChromeDriver coreDriver() {
			return delegator.coreDriver();
		}

		@Override
		public void close() {
			idleBrowsers.offer(this);
		}
	}
}
